; void halftone_asm (
; 	unsigned char *src,
; 	unsigned char *dst,
; 	int m,
; 	int n,
; 	int src_row_size,
; 	int dst_row_size
; );

; Parámetros:
; 	rdi = src
; 	rsi = dst
; 	rdx = m
; 	rcx = n
; 	r8 = src_row_size
; 	r9 = dst_row_size


global halftone_asm
section .data



section .text

halftone_asm:
    PUSH RBP
    MOV RBP,RSP
    PUSH RBX
    PUSH R12
    PUSH R13
    PUSH R14
    PUSH R15
    SUB RSP, 8

    ; no tenemos que procesar la ultima fila y columna
    dec rdx

    shr rcx, 1          ; si el nro de columnas es impar, 
    shl rcx, 1          ; me quedo con el par anterior

    xor r10, r10        ; r10: indice columna
    xor rbx, rbx        ; rbx: indice fila

                        ; rdi: fila actual origen
    lea r12, [rdi + r8] ; r12: siguiente fila origen
                        ; rsi: fila destino
    lea r13, [rsi + r9] ; r13: siguiente fila destino

    .ciclo:
    mov r11, r10
    add r11, 16
    cmp r11, rcx        ; indice_col + 16 > cant_columnas ?
    jbe .seguir
    lea r10, [rcx - 16]

    
    .seguir:

    movdqu xmm0, [rdi + r10]    ;xmm0: hhhh hhhh llll llll
    movdqu xmm1, [r12 + r10]
    
    movdqu xmm3, xmm0
    movdqu xmm4, xmm1

    pxor xmm2, xmm2

    punpcklbw xmm3, xmm2    ; xmm3: 0l0l 0l0l 0l0l 0l0l fila superior
    punpcklbw xmm4, xmm2    ; xmm4: 0l0l 0l0l 0l0l 0l0l fila inferior
    paddw xmm3, xmm4        ; xmm3: s1s2 s3s4 s5s6 s7s8
    phaddw xmm3, xmm2       ; xmm3: s1+s2 s3+s4 s5+s6 s7+s8  0000 0000

    movdqu xmm5, xmm0
    movdqu xmm4, xmm1

    punpckhbw xmm5, xmm2    ; xmm5: 0h0h 0h0h 0h0h 0h0h fila superior
    punpckhbw xmm4, xmm2    ; xmm4: 0h0h 0h0h 0h0h 0h0h fila inferior
    paddw xmm5, xmm4
    phaddw xmm2, xmm5       ; xmm2: 0000 0000 s1+s2 ..... s7+s8

    ;combino las sumas
    por xmm3, xmm2
    
    pxor xmm0, xmm0
    pxor xmm1, xmm1         ; en xmm0 y xmm1 voy a guardar el resultado


    ; t < 205
    ; para este caso no hago nada, el resultado ya tiene
    ; todos los pixeles en negro
        
    ; 205 < t < 410
    ; t < 410
    xor eax, eax
    mov ax, 410
    pinsrw xmm5, eax, 0
    pinsrw xmm5, eax, 1
    shufps xmm5, xmm5, 0h   ; xmm5: 410...
    pcmpgtw xmm5, xmm3      ; xmm5: mascara

    ; t > 205
    xor eax, eax
    mov ax, 205
    pinsrw xmm6, eax, 0
    pinsrw xmm6, eax, 1
    shufps xmm6, xmm6, 0h   ; xmm6: 205...
    movdqu xmm4, xmm3
    pcmpgtw xmm4, xmm6
    pcmpeqw xmm6, xmm3
    por xmm4, xmm6

    pand xmm5, xmm4

    mov eax, 0x00FF00FF
    pinsrd xmm6, eax, 0
    shufps xmm6, xmm6, 0h         ; xmm6: tiene el contenido correcto
    
    pand xmm6, xmm5               ; aplico la mascara
    por xmm0, xmm6

    ; como los pixeles de la fila inferior van en negro, no hago nada

    ; 410 < t < 615
    ; t < 615
    xor eax, eax
    mov ax, 615
    pinsrw xmm5, eax, 0
    pinsrw xmm5, eax, 1
    shufps xmm5, xmm5, 0h   ; xmm5: 615...
    pcmpgtw xmm5, xmm3
    ; t > 410
    xor eax, eax
    mov ax, 410
    pinsrw xmm6, eax, 0
    pinsrw xmm6, eax, 1
    shufps xmm6, xmm6, 0h   ; xmm6: 410...
    movdqu xmm4, xmm3
    pcmpgtw xmm4, xmm6
    pcmpeqw xmm6, xmm3
    por xmm4, xmm6

    pand xmm5, xmm4

    ; fila superior
    mov eax, 0x00FF00FF
    pinsrd xmm6, eax, 0
    shufps xmm6, xmm6, 0h   ; xmm6: tiene el contenido correcto
    
    pand xmm6, xmm5         ; aplico la mascara
    por xmm0, xmm6
    ; fila inferior
    mov eax, 0xFF00FF00
    pinsrd xmm6, eax, 0
    shufps xmm6, xmm6, 0h   ; xmm6: tiene el contenido correcto
    
    pand xmm6, xmm5         ; aplico la mascara
    por xmm1, xmm6


    ; 615 < t < 820
    xor eax, eax
    mov ax, 820
    pinsrw xmm5, eax, 0
    pinsrw xmm5, eax, 1
    shufps xmm5, xmm5, 0h   ; xmm5: 820...
    pcmpgtw xmm5, xmm3
    
    xor eax, eax
    mov ax, 615
    pinsrw xmm6, eax, 0
    pinsrw xmm6, eax, 1
    shufps xmm6, xmm6, 0h   ; xmm6: 615...
    movdqu xmm4, xmm3
    pcmpgtw xmm4, xmm6
    pcmpeqw xmm6, xmm3
    por xmm4, xmm6


    pand xmm5, xmm4

    ; fila superior
    mov eax, 0x00FF00FF
    pinsrd xmm6, eax, 0
    shufps xmm6, xmm6, 0h   ; xmm6: tiene el contenido correcto
    
    pand xmm6, xmm5         ; aplico la mascara
    por xmm0, xmm6
    ; fila inferior
    mov eax, 0xFFFFFFFF
    pinsrd xmm6, eax, 0
    shufps xmm6, xmm6, 0h   ; xmm6: tiene el contenido correcto
    
    pand xmm6, xmm5         ; aplico la mascara
    por xmm1, xmm6

    ; t > 820
    xor eax, eax
    mov ax, 820
    pinsrw xmm5, eax, 0
    pinsrw xmm5, eax, 1
    shufps xmm5, xmm5, 0h   ; xmm5: 820...
    movdqu xmm4, xmm3
    pcmpgtw xmm4, xmm5      ; si las sumas son mas grandes que 820
    pcmpeqw xmm5, xmm3
    por xmm5, xmm4          ; o iguales a 820

    por xmm1, xmm5
    por xmm0, xmm5

    ; finalmente escribo
    movdqu [rsi + r10], xmm0
    movdqu [r13 + r10], xmm1

    add r10, 16 
    cmp r10, rcx
    jb .ciclo
    
    xor r10, r10        ; indice_columna = 0
    lea rdi, [rdi + 2 * r8]
    lea r12, [r12 + 2 * r8]
    lea rsi, [rsi + 2 * r9]
    lea r13, [r13 + 2 * r9]
    add rbx, 2          ; indice_fila += 2;
    cmp rbx, rdx
    jb .ciclo

    ADD RSP, 8
    POP R15
    POP R14
    POP R13
    POP R12
    POP RBX
    POP RBP


    ret
